/*
 * dhmm.h
 *
 *  Created on: Aug 11, 2011
 *      Author: tqlong
 */

#ifndef DHMM_H_
#define DHMM_H_

#include "hmm.h"

/** Independent observation duration HMM */
class DurationHMM
{
public:
  typedef arma::ivec       ivec;
  typedef arma::mat        dmat;
  typedef arma::vec        dvec;

  typedef std::vector<ivec>     ivecvec;
  typedef std::vector<dvec>     dvecvec;
  typedef std::vector<ivecvec>  ivecvecvec;
  typedef std::vector<dvecvec>  dvecvecvec;
public:
  DurationHMM(int n_state, int n_observation);

  const dmat& transition() const { return a_; }
  const dmat& emission()   const { return b_; }
  const dvec& start()      const { return pi_; }
  const ivec& duration(int state) const { return d_[state]; }

  void setTransition(const dmat& a);
  void setEmission(const dmat& b);
  void setStart(const dvec& pi);
  void setDuration(int state, const ivec& d, const dvec& p);

  void dump();

  void genSeq(int T, ivec& o, ivec& q, ivec& d);

  double seqProbability(const ivec& o);
  //void decode(const ivec& o, ivec& q, ivec& d);
  void train(const ivec& o);
protected:
  int Q_, K_;
  dmat a_, b_;  // in log-space
  dvec pi_;     // in log-space
  ivecvec d_;   // duration of each state
  dvecvec p_;   // probability of each duration per state
protected:
  double dprob(const ivec& o, int t, int m, int d);
  void computeAlpha(const ivec& o);
  void computeBeta(const ivec& o);
  void computeAlphaS(const ivec& o);
  void computeBetaS(const ivec& o);

  void reestimateP(const ivec& o);
  void reestimateB(const ivec& o);

  dvecvec alpha_, beta_, kappa_, alphaS_, betaS_;
  dvec beta0S_;
};

typedef DurationHMM dhmm;

#endif /* DHMM_H_ */
